﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace WPFClient.Codes
{
    public class TCPHelper
    {
        #region 属性部分

        /// <summary>
        /// 当前的TCP连接
        /// </summary>
        public TcpClient CurrentClient { get; set; }

        /// <summary>
        /// 服务器的IP地址
        /// </summary>
        public string IpAddress { get; set; }

        /// <summary>
        /// 服务器的端口
        /// </summary>
        public int Port { get; set; }

        /// <summary>
        /// 接收的数据长度
        /// </summary>
        public int DataLength { get; set; } = 1024;

        #endregion

        /// <summary>
        /// 构造函数    
        /// </summary>
        /// <param name="ipAddress"></param>
        /// <param name="port"></param>
        public TCPHelper(string ipAddress, int port)
        {
            this.IpAddress = ipAddress;
            this.Port = port;
        }

        /// <summary>
        /// 构造函数    
        /// </summary>
        /// <param name="ipAddress"></param>
        /// <param name="port"></param>
        public TCPHelper(string ipAddress, string port)
        {
            this.IpAddress = ipAddress;
            this.Port = int.Parse(port);
        }

        public async Task Connect(Action<byte[], int> receiveDataCallBack, CancellationToken cancellationToken = default,Action<Exception> receiveDataErrorCallBack = null)
        {
            // 清理现有连接
            this.Disconnect();
            this.CurrentClient = new TcpClient();

            try
            {
                await this.CurrentClient.ConnectAsync(this.IpAddress, this.Port);

                if (this.CurrentClient.Connected)
                {
                    _ = StartReceivingAsync(receiveDataCallBack, cancellationToken, receiveDataErrorCallBack);
                }
                else
                {
                    throw new Exception("连接未成功建立");
                }
            }
            catch (Exception ex)
            {
                this.Disconnect();
                throw new Exception($"连接服务器失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 开始接收数据
        /// </summary>
        /// <param name="receiveDataCallBack"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        private async Task StartReceivingAsync(Action<byte[], int> receiveDataCallBack, CancellationToken cancellationToken, Action<Exception> receiveDataErrorCallBack)
        {
            try
            {
                using (NetworkStream stream = this.CurrentClient.GetStream())
                {
                    byte[] buffer = new byte[this.DataLength]; // 复用缓冲区

                    while (this.CurrentClient?.Connected == true && !cancellationToken.IsCancellationRequested)
                    {
                        try
                        {
                            int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken);

                            if (bytesRead == 0)
                                break; // 连接已正常关闭

                            // 创建数据副本传递给回调
                            byte[] dataCopy = new byte[bytesRead];
                            Array.Copy(buffer, dataCopy, bytesRead);

                            receiveDataCallBack?.Invoke(dataCopy, bytesRead);
                        }
                        catch (Exception ex)
                        {
                            if (receiveDataErrorCallBack != null)
                                receiveDataErrorCallBack(ex);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // 记录日志，可以选择触发错误回调
                //暂时先这样写，日后再把日志模块丢进来
                Console.WriteLine($"接收数据过程中发生错误: {ex.Message}");
            }
            finally
            {
                // 清理资源
                this.Disconnect(); ;
            }
        }

        // 提供断开连接的方法
        public void Disconnect()
        {
            if (this.CurrentClient != null)
            {
                this.CurrentClient?.Close();
                this.CurrentClient = null;
            }
        }
    }
}
